package com.twm.handler;

import com.alibaba.fastjson.JSONObject;
import com.twm.boot.SpringContextHolder;
import com.twm.entity.RpcRequest;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.springframework.aop.support.AopUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;

/*
自定义业务处理器
 */
public class UserServiceHandler extends ChannelInboundHandlerAdapter {

    /**
     * 当客户读取数据时， 该方法会被调用
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        RpcRequest rpcRequest = JSONObject.parseObject(msg.toString(), RpcRequest.class);
        String className = rpcRequest.getClassName();
        String methodName = rpcRequest.getMethodName();
        Object[] parameters = rpcRequest.getParameters();
        Class<?>[] parameterTypes = rpcRequest.getParameterTypes();
        String requestId = rpcRequest.getRequestId();

        ApplicationContext applicationContext = SpringContextHolder.getApplicationContext();
        Object bean = applicationContext.getBean(requestId);

        Method method = getMethod(bean.getClass(), methodName);

        if(method == null) {
            throw new RuntimeException(String.format("没有找到%s方法", methodName));
        }

        // 获取方法执行的参数
        List<Object> objects = getMethodParamList(parameters, parameterTypes);

        // 执行方法
        Object invoke = method.invoke(bean, objects);

        //1、判断当前请求是否符合规则
//        UserServiceImpl userService = new UserServiceImpl();
        //2、符合规则， 调用实现类到一个result
//        String request = userService.getRpcRequest(msg);
        //3、把调用实现类的方法活的的结果写到客户端
        ctx.writeAndFlush(invoke);
    }

    /**
     * 获取方法实际参数，不支持基本类型
     */
    private List<Object> getMethodParamList(Object[] paramMap, Class<?>[] parameterTypes) throws Exception {
        List<Object> objectList = new ArrayList<>();
        for (int i = 0; i < paramMap.length; i++) {
            Object convert = ConvertUtils.convert(paramMap[i], parameterTypes[i]);
            objectList.add(convert);
        }
        return objectList;
    }

    /**
     * 获取目标方法
     * @param proxyObject
     * @param methodStr
     * @return
     */
    private Method getMethod(Class proxyObject, String methodStr) {
        Method[] methods = proxyObject.getMethods();

        for(Method method : methods) {
            if(method.getName().equalsIgnoreCase(methodStr)) {
                return method;
            }
        }

        return null;
    }

}
